using System;
using System.Collections;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
using Microsoft.VisualBasic;

using NCover.Objects;
using NCover.Report;
using NUnit.Framework;

namespace NCover
{
	/// <summary>
	/// Summary description for TestUtilities.
	/// </summary>
	public class TestUtilities
	{
		static CSharpCodeProvider cSharpCompiler;
		static ICodeCompiler compiler;
		static CompilerParameters compileParameters;

		static VBCodeProvider vbCompilerProvider;
		static ICodeCompiler vbCompiler;
		static CompilerParameters vbCompileParameters;
		
		static TestUtilities()
		{
			cSharpCompiler = new CSharpCodeProvider();
			compiler = cSharpCompiler.CreateCompiler();
			compileParameters = new CompilerParameters();

			vbCompilerProvider = new VBCodeProvider();
			vbCompiler = vbCompilerProvider.CreateCompiler();
			vbCompileParameters = new CompilerParameters();
		}

		/// <summary>
		/// Checks code compiles.
		/// </summary>
		/// <param name="code">Code must contain only one Type with one method in it</param>
		/// <param name="expectedValue">Value that the function should return.</param>
		public static object AssertCompiles(string [] code, string typeName)
		{	
			compileParameters.GenerateInMemory = true;
			compileParameters.TreatWarningsAsErrors = true;
			compileParameters.ReferencedAssemblies.Add( typeof( NCover.NCoverCheck ).Assembly.CodeBase.Substring("file:///".Length) );
			
			CompilerResults resultsOfCompile = compiler.CompileAssemblyFromSourceBatch(compileParameters, code);

			NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(262); NCover.NCoverCheck.Add(262); NCover.NCoverCheck.Add(261); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(263); foreach (string outline in resultsOfCompile.Output)
			{
				System.Diagnostics.Debug.WriteLine(outline);
			}

			Assert.AreEqual(0, resultsOfCompile.Errors.Count);
			Assert.AreEqual(0, resultsOfCompile.Output.Count);

			Assembly assembly = resultsOfCompile.CompiledAssembly;
			Assert.IsNotNull(assembly);

			Type type = assembly.GetType(typeName);

			NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(262); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(264); return GetNormalMethod(type).Invoke(null, new object[]{});
		}

		/// <summary>
		/// Checks code compiles.
		/// </summary>
		/// <param name="code">Code must contain only one Type with one method in it</param>
		/// <param name="expectedValue">Value that the function should return.</param>
		public static object AssertVbCompiles(string [] code, string typeName)
		{	
			vbCompileParameters.GenerateInMemory = true;
			
			vbCompileParameters.TreatWarningsAsErrors = true;
			vbCompileParameters.ReferencedAssemblies.Add( typeof( NCover.NCoverCheck ).Assembly.CodeBase.Substring("file:///".Length) );
		//	vbCompileParameters.ReferencedAssemblies.Add( @"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Microsoft.VisualBasic.dll" );
			
			//insert magic vb imports
			for (int i = 0; i < code.Length; i++)
			{
				code[i] = @"Imports Microsoft.VisualBasic.Interaction
" + code[i];
			}

			CompilerResults resultsOfCompile = vbCompiler.CompileAssemblyFromSourceBatch(vbCompileParameters, code);

			NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(263); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(265); foreach (string outline in resultsOfCompile.Output)
			{
				System.Diagnostics.Debug.WriteLine(outline);
			}

			Assert.AreEqual(0, resultsOfCompile.Errors.Count);
			Assert.AreEqual(0, resultsOfCompile.Output.Count);

			Assembly assembly = resultsOfCompile.CompiledAssembly;
			Assert.IsNotNull(assembly);

			Type type = assembly.GetType(typeName);

			NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(264); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(266); return GetNormalMethod(type).Invoke(null, new object[]{});
		}

		/// <summary>
		/// Checks code compiles.
		/// </summary>
		/// <param name="code">Code must contain only one Type with one method in it</param>
		/// <param name="expectedValue">Value that the function should return.</param>
		public static void AssertCompilesAndReturns(string [] code, string typeName, object expectedValue)
		{			
			Assert.AreEqual(expectedValue, AssertCompiles(code, typeName));
		}

		private static MethodInfo GetNormalMethod(Type t)
		{
			ArrayList potentials = new ArrayList();
			NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(265); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(267); foreach (MethodInfo methInfo in t.GetMethods())
			{
				if (methInfo.IsSpecialName && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(275) && NCover.NCoverCheck.Add(275) && NCover.NCoverCheck.Add(274) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(276))
					continue;

				if (methInfo.IsConstructor && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(275) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(277))
					continue;

				if (methInfo.DeclaringType == typeof(object) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(276) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(278))
					continue;

				potentials.Add(methInfo);
			}

			Assert.AreEqual(1, potentials.Count);
			NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(266); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(268); return (MethodInfo) potentials[0];
		}

		public static bool WasHit(CoveragePoint[] points, bool[] results, int lineNumber)
		{
			bool resultFound = false;
			bool result = false;

			NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(267); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(269); foreach (CoveragePoint p in points)
			{
				if (p.LineNumber == lineNumber && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(277) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279))
				{
					if (resultFound && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(278) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280))
					{
						NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(268); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(270); throw new ApplicationException("Multiple coverage points are on line " + lineNumber  + ". Refactor code...");
					}
					resultFound = true;
					
					if (p.AbsoluteNumber > results.Length && NCover.NCoverCheck.Add(282) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(279) && NCover.NCoverCheck.Add(282) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281))
					{
						NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(269); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(271); return false;
					}

					result = results[p.AbsoluteNumber - 1];
				}
			}

			if (!resultFound && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(283) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(281) && NCover.NCoverCheck.Add(280) && NCover.NCoverCheck.Add(283))
			{
				Assert.Fail("no coverage point found on line " + lineNumber  + ".");
			}
			NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(270); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(272); return result;
		}
		public static CoverageReport PopulateReport50percent()
		{
			CoverageReport coverageReport = new CoverageReport();
			coverageReport.SourceDir = Environment.CurrentDirectory;
			coverageReport.DefaultNamespace = new CoverageNamespace();
			
			CoverageFile coverageFile = new CoverageFile(@"c:\adire");
			coverageReport.DefaultNamespace.Members.Add(coverageFile);

			coverageFile.CoveragePoints.Add(new CoveragePoint("afile","anamespace",0,0, false));
			coverageFile.CoveragePoints.Add(new CoveragePoint("afile2","anamespace",0,1, true));
			NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(271); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(273); return coverageReport;
		}

		public static CoverageReport PopulateReport33percentWithMultipleNamespaces()
		{
			CoverageReport coverageReport = new CoverageReport();
			coverageReport.SourceDir = Environment.CurrentDirectory;
			coverageReport.DefaultNamespace = new CoverageNamespace();
			
			CoverageFile coverageFile = new CoverageFile(@"c:\adir");
			coverageReport.DefaultNamespace.Members.Add(coverageFile);
			coverageFile.CoveragePoints.Add(new CoveragePoint("afile","anamespace",0,0, false));
			coverageFile.CoveragePoints.Add(new CoveragePoint("afile2","anamespace",0,1, true));

			CoverageNamespace ns = coverageReport.DefaultNamespace.GetNamespace(new string[] { "arealnamespace"});

			CoverageFile coverageFile2 = new CoverageFile(@"c:\adir2");
			coverageFile2.CoveragePoints.Add(new CoveragePoint("afile3","arealnamespace",1,1, false));
			ns.Members.Add(coverageFile2);
			
			NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(276); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(272); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(274); return coverageReport;
		}

		public static CoverageReport PopulateReport33percent()
		{
			CoverageReport coverageReport = new CoverageReport();
			coverageReport.SourceDir = Environment.CurrentDirectory;
			coverageReport.DefaultNamespace = new CoverageNamespace();
			
			CoverageFile coverageFile = new CoverageFile(@"c:\adir");
			coverageReport.DefaultNamespace.Members.Add(coverageFile);

			coverageFile.CoveragePoints.Add(new CoveragePoint("afile","anamespace",0,0, false));
			coverageFile.CoveragePoints.Add(new CoveragePoint("afile2","anamespace",0,1, true));
			coverageFile.CoveragePoints.Add(new CoveragePoint("afile2","anamespace",1,1, false));
			
			NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(277); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(274); NCover.NCoverCheck.Add(273); NCover.NCoverCheck.Add(276); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(275); NCover.NCoverCheck.Add(275); return coverageReport;
		}
		 
	}
}














